package main

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"github.com/gin-gonic/gin"
)

func main() {
	//开启服务 : 所有的路由都在这个函数中(如果涉及优化:后续再调整)

	//为了调试方便(方便看运行情况:采用gin自带的中间件:Logger()&&Recover())

	r := gin.Default()

	//静态资源加载:static 访问
	r.StaticFS("/static", http.Dir("./software2203shop/static"))

	//加载模板文件
	r.LoadHTMLGlob("./software2203shop/tpl/*")

	//中间件:验证用户是否登录(如果用户登录,将用户的信息存入到某个变量,未来在需要的时候进行验证和调用即可)
	var user users.Users

	r.Use(func(ctx *gin.Context) {
		//验证用户是否登录:看session中是否有user信息
		val := tools.GetSession(ctx, "user")

		user, _ = val.(users.Users)
		fmt.Println(user)

		//进入下一个路由或者中间件
		ctx.Next()
	})

	//1.首页路由: 只能用户输入网址即可，不需要输入对应的路由路径(根目录路由)
	r.GET("/", func(ctx *gin.Context) {

		//获取首页相关数据
		products := products.GetIndexProducts()
		// fmt.Println(products)

		//最后一件事情:加载模板
		ctx.HTML(200, "index.html", gin.H{
			"products": products,
			"user":     user,
		})
	})

	// 2.特价商品页面
	r.GET("/special", func(ctx *gin.Context) {

		page := ctx.DefaultQuery("page", "1")
		current, _ := strconv.Atoi(page)
		//获取分页信息
		pageInfo := tools.GetPage(products.GetSpecialCounts(), current)

		//加载数据
		specialProducts := products.GetSpecialProducts(pageInfo.Current, tools.GetPageCount())

		//显示特价商品页
		ctx.HTML(200, "tejia.html", gin.H{
			"products": specialProducts,
			"user":     user,
			"pageInfo": pageInfo,
			"router":   "special",
		})
	})

	//3.男士商品页面

	r.GET("/male", func(ctx *gin.Context) {

		//如果用户有提交数据:要先接受数据 进行验证(合法性和合理性)
		page := ctx.DefaultQuery("page", "1")
		current, _ := strconv.Atoi(page)

		//获取分页信息
		pageInfo := tools.GetPage(products.GetGenderCounts("男"), current)

		//数据获取: 新品数据最多5条,男士商品数据,所有品牌数据
		maleProducts := products.GetGenderProducts("男", pageInfo.Current, tools.GetPageCount())
		brands := brands.GetBrands()
		newProducts := products.GetNewProducts()

		//加载显示数据
		ctx.HTML(200, "boys.html", gin.H{
			"products":    maleProducts,
			"brands":      brands,
			"newProducts": newProducts,
			"user":        user,
			"router":      "male",
			"pageInfo":    tools.GetPage(products.GetGenderCounts("男"), current),
		})

	})

	// 4.女士商品页面

	r.GET("/lady", func(ctx *gin.Context) {

		//如果用户有提交数据:要先接受数据 进行验证(合法性和合理性)
		page := ctx.DefaultQuery("page", "1")
		current, _ := strconv.Atoi(page)

		//获取分页信息
		pageInfo := tools.GetPage(products.GetGenderCounts("女"), current)

		//数据获取: 新品数据最多5条,女士商品数据,所有品牌数据
		ladyProducts := products.GetGenderProducts("女", pageInfo.Current, tools.GetPageCount())
		brands := brands.GetBrands()
		newProducts := products.GetNewProducts()

		//加载显示数据
		ctx.HTML(200, "girl.html", gin.H{
			"products":    ladyProducts,
			"brands":      brands,
			"newProducts": newProducts,
			"user":        user,
			"router":      "lady",
			"pageInfo":    tools.GetPage(products.GetGenderCounts("女"), current),
		})

	})

	//寄卖页面
	r.GET("/jimai", func(ctx *gin.Context) {
		ctx.HTML(200, "jimai.html", gin.H{})
	})

	//商品详情，路由后面需要跟一个/:key,表示路由后接一个参数结果,使用key变量保存结果
	r.GET("/detail/:id", func(ctx *gin.Context) {
		//接收数据
		id := ctx.Param("id")
		//数据验收
		//数据操作(基于ID查询数据)
		//将数据结果返回
		product := products.GetDetail(id)

		//判定数据是否存在
		if product.Product_id == 0 {
			ctx.HTML(200, "redirect.html", gin.H{
				"tips":   "找不到要访问的商品!",
				"target": "/",
			})
			return
		}

		//获取热销商品(前三个)
		hotProducts := products.GetBrandProduct(product.Brand_id)

		ctx.HTML(http.StatusOK, "xiangxi.html", gin.H{
			"product":  product,
			"products": hotProducts,
		})
	})

	//注册功能
	r.GET("/register", func(ctx *gin.Context) {

		//加载模板
		ctx.HTML(200, "reg.html", gin.H{})

	})

	r.POST("/checkRegister", func(ctx *gin.Context) {

		//接收数据
		var userinfo users.UserInfoRegister
		fmt.Println(userinfo)
		fmt.Println("接收到数据")

		if err := ctx.ShouldBindWith(&userinfo, binding.Form); err != nil {
			ctx.HTML(200, "redirect.html", gin.H{
				"tips":   err.Error(),
				"target": "/register",
			})

			return
		}

		if err := users.CheckRegister(userinfo); err != nil {
			ctx.HTML(200, "redirect.html", gin.H{
				"tips":   err.Error(),
				"target": "/register",
			})
		}

		// 注册成功，返回成功页面
		ctx.HTML(200, "redirect.html", gin.H{
			"tips":   "注册成功,请先登录",
			"target": "/login",
		})

		fmt.Println("数据没错")
	})

	//登录入口
	r.GET("/login", func(ctx *gin.Context) {
		referer := ctx.Request.Header.Get("referer")
		ctx.HTML(200, "login.html", gin.H{
			"referer": referer,
		})
	})

	//登录验证
	r.POST("/checkLogin", func(ctx *gin.Context) {
		//接收数据
		username := ctx.PostForm("username")
		password := ctx.PostForm("password")
		referer := ctx.PostForm("referer")

		//数据加工(提交的字符串数据必做的事情):去除两边多余的可能出现的空格
		username = strings.TrimSpace(username)
		password = strings.TrimSpace(password)

		//数据验证:合法性(是否满足规则) 和 合理性验证(是否匹配数据)

		//简单验证  不为空验证

		if username == "" {
			ctx.HTML(200, "redirect.html", gin.H{
				"tips":   "用户名不为空",
				"target": "/login",
			})
			return
		}

		if password == "" {
			ctx.HTML(200, "redirect.html", gin.H{
				"tips":   "密码不为空",
				"target": "/login",
			})
			return
		}
		//合理性验证:验证数据库(用户名是否存在,密码是否正确)
		user, err := users.CheckLogin(username, password)

		if err != nil {
			//有错误
			ctx.HTML(200, "redirect.html", gin.H{
				"tips":   err.Error(),
				"target": "/login",
			})
			return
		}

		fmt.Println(user)

		//跳转到首页(确切的讲，应该是跳转到上一次进入登录页的页面)
		//获取当前请求页面的上一个路由，通过http协议中的referer协议获取

		err = tools.SetSession(ctx, "user", user)

		if err != nil {
			//有错误
			ctx.HTML(200, "redirect.html", gin.H{
				"tips":   err.Error(),
				"target": "/login",
			})
			return
		}

		// fmt.Println(ctx.Request.Header.Get("referer"))
		ctx.HTML(200, "redirect.html", gin.H{
			"tips":   "登录成功!",
			"target": referer,
		})

	})

	// 获取验证码字符串
	r.GET("/getCaptcha", func(ctx *gin.Context) {
		// 调用 GetCaptcha 生成验证码
		captcha := tools.GetCaptcha()
		// 返回验证码
		ctx.String(200, captcha)
		fmt.Println(captcha)
	})

	//寻表专区
	r.GET("/huiyuan", func(ctx *gin.Context) {
		ctx.HTML(200, "huiyuan.html", gin.H{})
	})
	r.GET("changePassword1", func(ctx *gin.Context) {
		ctx.HTML(200, "changePassword.html", gin.H{})
	})
	// 修改密码的请求数据结构体
	type ChangePasswordForm struct {
		Username    string `form:"Username" binding:"required"`
		OldPassword string `form:"OldPassword" binding:"required"`
		NewPassword string `form:"NewPassword" binding:"required"`
	}

	// 修改密码的处理函数
	r.POST("/changePassword", func(ctx *gin.Context) {
		// 定义一个ChangePasswordForm变量，用于接收和绑定请求中的表单数据
		var form ChangePasswordForm
		// 使用ShouldBind方法将请求中的表单数据绑定到form变量
		if err := ctx.ShouldBind(&form); err != nil {
			// 如果绑定失败，返回错误信息，并以400状态码响应
			ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		// 查找用户，验证用户名和旧密码是否正确
		user, err := users.CheckLogin(form.Username, form.OldPassword)
		if err != nil {
			// 如果用户验证失败（例如，用户名或密码错误），返回错误信息，并以400状态码响应
			ctx.JSON(http.StatusBadRequest, gin.H{"error": "当前密码错误"})
			return
		}

		// 使用MD5算法加密新密码
		hash := md5.Sum([]byte(form.NewPassword))
		encodedNewPassword := hex.EncodeToString(hash[:])
		// 更新用户密码为加密后的新密码
		user.Password = encodedNewPassword
		// 保存更新到数据库
		if err := database.Gdb.Save(&user).Error; err != nil {
			// 如果保存失败，返回错误信息，并以500状态码响应
			ctx.JSON(http.StatusInternalServerError, gin.H{"error": "更新密码失败"})
			return
		}

		// 如果密码更新成功，返回成功信息，并以200状态码响应
		ctx.JSON(http.StatusOK, gin.H{"message": "密码更新成功"})
	})

	// 客服对话页面路由
	r.GET("/customer-service", func(ctx *gin.Context) {
		ctx.HTML(200, "customer-service.html", gin.H{})
	})

	//启动服务
	r.Run(":80")
}
